const fs = require('fs');
const path = require('path');
const { PNG } = require('pngjs');

// HydrodynamicData 类
class HydrodynamicData {
    constructor(
        i = 0,
        j = 0,
        layer = 0,
        totalFlux = 0,
        waterLevel = 0,
        waterDepth = 0,
        USpeed = 0,
        VSpeed = 0,
        WSpeed = 0,
        flux = 0,
        temperature = 0,
        salinity = 0,
        colorants = 0,
        X = null, // 假设为number或null
        Y = null, // 假设为number或null
        Z = null  // 假设为number或null
    ) {
        this.i = i;
        this.j = j;
        this.layer = layer;
        this.totalFlux = totalFlux;
        this.waterLevel = waterLevel;
        this.waterDepth = waterDepth;
        this.USpeed = USpeed;
        this.VSpeed = VSpeed;
        this.WSpeed = WSpeed;
        this.flux = flux;
        this.temperature = temperature;
        this.salinity = salinity;
        this.colorants = colorants;
        this.X = X;
        this.Y = Y;
        this.Z = Z;
    }
}

// NOTE:本地nodejs环境下运行
function Main() {
    // TODO:需修改替换为你自己的文件夹路径
    const inputFileDir = "E:\\组内内容\\水生态环境数字孪生智能系统研发\\模型模拟结果文件\\wuhanduan\\res\\TIME_HYD";
    
    // NOTE: 遍历其中的所有dat后缀文件进行处理
    fs.readdir(inputFileDir, (err, files) => {
        if (err) {
            console.error('读取文件夹出错:', err);
            return;
        }
    
        // 过滤出所有以 .DAT 结尾的文件
        const txtFiles = files.filter(file => path.extname(file) === '.DAT');
    
        // 遍历 .DAT 文件并读取内容
        txtFiles.forEach(file => {
            const filePath = path.join(inputFileDir, file);
            console.log("filePath:",filePath);
            // 获取不带扩展名的文件名
            const fileNameWithoutExt = path.basename(file, '.DAT');
        
            // 读取文件内容
            fs.readFile(filePath, 'utf8', (err, data) => {
                if (err) {
                    console.error(`读取文件 ${file} 出错:`, err);
                    return;
                }
                
                // 输出文件名和内容
                console.log(`文件名（无后缀）: ${fileNameWithoutExt}`);
                // 输出文件内容
                // console.log(`文件 ${file} 的内容:`);
                // console.log(data);

                ParseDATFromFileContent(data,fileNameWithoutExt);

            });
        });
    });

    console.log("Main Function is running.");
}

// 解析 DAT 文件内容
function ParseDATFromFileContent(fileContent,fileName) {
    // 去掉首行无用数据
    const lines = fileContent.split('\n').slice(2); // 假设前两行是标题和表头，从第三行开始读取数据

    let leftHydroData = [];
    let rightHydroData = [];

    let count_num = 0;
    lines.forEach(line => {
        if (line.trim() === '') return; // 跳过空行

        const values = line.split(/\s+/).map(value => value.trim());
        count_num++;

        // 文件中的数据格式严格按照提供的格式，每个字段依次对应
        const [
            , I, J, level, totalFlux, waterLevel, waterDepth, USpeed, VSpeed, WSpeed, flux, temperature, salinity, colorants, X, Y, Z
        ] = values;

        const hydrodynamicData = new HydrodynamicData(
            parseInt(I, 10), parseInt(J, 10), parseInt(level, 10),
            parseFloat(totalFlux), parseFloat(waterLevel), parseFloat(waterDepth),
            parseFloat(USpeed), parseFloat(VSpeed), parseFloat(WSpeed),
            parseFloat(flux), parseFloat(temperature), parseFloat(salinity), parseFloat(colorants),
            parseFloat(X), parseFloat(Y), parseFloat(Z)
        );

        // 读取dat中的数据
        if (count_num >= 5 && count_num <= 343) { // 河流水面最左侧
            if (count_num % 2 === 1) {
                leftHydroData.push(hydrodynamicData);
            }
        } else if (count_num >= 706 && count_num <= 875) { // 河流水面最右侧
            rightHydroData.push(hydrodynamicData);
        } else {

        }
    });


    // 创建记录值的图片
    CreateImageryWithValue(leftHydroData, rightHydroData,fileName);

}

// TODO:修改为你自己想要的输出文件路径
const outputDir = './images';

// 设置输出图片大小 IMGSIZE * IMGSIZE
const IMGSIZE = 128;

function CreateImageryWithValue(leftHydroData, rightHydroData,fileName) {
    const pointCount = leftHydroData.length;

    let leftPointValue = [];
    let rightPointValue = [];

    for (let i = 0; i < pointCount; i++) {
        leftPointValue.push(leftHydroData[i].temperature);
        rightPointValue.push(rightHydroData[i].temperature);
    }

    let valueArray = [...leftPointValue, ...rightPointValue];

    let valueImagerArray = [];
    for (let i = 0; i < pointCount - 1; i++) {
        valueImagerArray.push(
            valueArray[i], valueArray[i + 1], valueArray[pointCount + i],
            valueArray[i + 1], valueArray[pointCount + i + 1], valueArray[pointCount + i]);
    }


    let outputFile = `${outputDir}\\${fileName}.png`;
    
    console.log('outputFile:',outputFile);
   CreateImayerFromData(IMGSIZE, valueImagerArray,outputFile);
   
   return;
}

// 将 CreateImayerFromData 修改为使用 pngjs
function CreateImayerFromData(imgSize, valueData,outputFile) {
    const maxValue = Math.max(...valueData);
    const minValue = Math.min(...valueData);
    console.log(`valueData data, max:${maxValue},min:${minValue}`);

    const size = imgSize;
    const png = new PNG({ width: size, height: size });

    for (let i = 0; i < valueData.length; i++) {
        const value = valueData[i]; // 获取顶点中记录的值
        const x = i % size; // 计算x坐标
        const y = Math.floor(i / size); // 计算y坐标

        const idx = (size * y + x) * 4; // 获取像素在图像数据中的位置
        let colorValue = Value2Color(value, minValue, maxValue);

        png.data[idx] = colorValue[0];     // R
        png.data[idx + 1] = colorValue[1]; // G
        png.data[idx + 2] = colorValue[2]; // B
        png.data[idx + 3] = 255;           // A
    }

    // 保存图像为 PNG 格式
    png.pack().pipe(fs.createWriteStream(outputFile));
}

// 将值映射到颜色
function Value2Color(value, lowValue = 10, highValue = 25) {
    if (value < lowValue || value > highValue) {
        console.error(`Value must be between ${lowValue} and ${highValue}`);
        if (value < lowValue) value = lowValue;
        else if (value > highValue) value = highValue;
    }

    const normalizedValue = (value - lowValue) / (highValue - lowValue);
    let hue;
    hue = normalizedValue * 120 + (normalizedValue > 0.5 ? (normalizedValue - 0.5) * 60 : 0);

    const saturation = 100;
    const lightness = 50;

    function hslToRgb(h, s, l) {
        s /= 100;
        l /= 100;
        const c = (1 - Math.abs(2 * l - 1)) * s;
        const x = c * (1 - Math.abs((h / 60) % 2 - 1));
        const m = l - c / 2;
        let r, g, b;
        if (0 <= h && h < 60) {
            r = c; g = x; b = 0;
        } else if (60 <= h && h < 120) {
            r = x; g = c; b = 0;
        } else if (120 <= h && h < 180) {
            r = 0; g = c; b = x;
        } else if (180 <= h && h < 240) {
            r = 0; g = x; b = c;
        } else if (240 <= h && h < 300) {
            r = x; g = 0; b = c;
        } else {
            r = c; g = 0; b = x;
        }
        r = Math.round((r + m) * 255);
        g = Math.round((g + m) * 255);
        b = Math.round((b + m) * 255);

        return [r, g, b];
    }

    return hslToRgb(hue, saturation, lightness);
}

Main();
